# coding=utf8
__author__ = 'lijian'
import logging
import os
import datetime

from entity import *
import setting
from xml.dom import minidom
from utils import byteUtil

_terms = []

_planLampTasks = []

_planGroupTasks = []

_planTermTasks = []

_groups = []

def getAllTerms():
    return tuple(_terms)


def findTermByGroup(groupNo):
    value = []
    for term in _terms:
        for g in term.groups:
            if g == groupNo:
                value.append(term)
                break
    return value


def findTermByDeviceId(deviceId):
    for term in _terms:
        if term.deviceId == deviceId:
            return term
    return None


def findTremByUID(uid):
    for term in _terms:
        if byteUtil.compareList(term.uid, uid):
            return term
    return None


def addTerm(term):
    exist = findTermByDeviceId(term.deviceId)
    if not exist:
        _terms.append(term)
    else:
        logging.debug("term %d exist,replace it" % exist.deviceId)
        _terms.remove(exist)
        _terms.append(term)


def findHolder(holderNo):
    for t in _terms:
        for h in t.holders:
            if h.holderNo == holderNo:
                return h

    return None


def getAllHolder():
    holders = []
    for term in _terms:
        for holder in term.holders:
            holders.append(holder)
    return holders


def getMaxHolderNo():
    maxNo = 0
    for term in _terms:
        for holder in term.holders:
            if holder.holderNo > maxNo:
                maxNo = holder.holderNo
    return maxNo


def saveLamps():
    impl = minidom.getDOMImplementation()
    dom = impl.createDocument(None, 'lamps', None)
    root = dom.documentElement

    for term in _terms:
        termEle = dom.createElement('lamp')
        termEle.setAttribute("deviceId", "%d" % term.deviceId)
        termEle.setAttribute("uid", "%r" % (term.uid,))
        termEle.setAttribute("enable", "%d" % term.enable)
        termEle.setAttribute("loopFlag", "%d" % term.loopFlag)
        termEle.setAttribute("poleNo", "%d" % term.poleNo)
        termEle.setAttribute("sync", "%d" % term.sync)
        termEle.setAttribute("groups", "%r" % (term.groups,))

        for holder in term.holders:
            ele = dom.createElement("holder")
            ele.setAttribute("holderNo", "%d" % holder.holderNo)
            ele.setAttribute("enable", "%d" % holder.enable)
            ele.setAttribute("lineNo", "%d" % holder.lineNo)
            ele.setAttribute("phase", "%d" % holder.phase)
            ele.setAttribute("loopNo", "%d" % holder.loopNo)
            termEle.appendChild(ele)

        root.appendChild(termEle)

    f = open(setting.LAMPS_FILE_PATH, 'w')
    dom.writexml(f, addindent='  ', newl='\n', encoding='utf-8')
    f.close()

    os.system("sync")




def loadLamps():
    global _terms

    if not os.path.exists(setting.LAMPS_FILE_PATH):
        logging.warn("%s not exist" % setting.LAMPS_FILE_PATH)
        return

    try:
        doc = minidom.parse(setting.LAMPS_FILE_PATH)
        root = doc.documentElement

        lampElements = root.getElementsByTagName("lamp")
        for ele in lampElements:
            deviceId = int(ele.getAttribute("deviceId"))
            uid = eval(ele.getAttribute("uid"))
            enable = int(ele.getAttribute("enable"))
            loopFlag = int(ele.getAttribute("loopFlag"))
            poleNo = int(ele.getAttribute("poleNo"))
            sync = False if ele.getAttribute("sync") == "0" else True
            groups = eval(ele.getAttribute("groups"))

            term = Term(deviceId, uid, enable, loopFlag, poleNo, sync, list(groups))
            _terms.append(term)

            holderElements = ele.getElementsByTagName("holder")
            for he in holderElements:
                holderNo = int(he.getAttribute("holderNo"))
                lineNo = int(he.getAttribute("lineNo"))
                loopNo = int(he.getAttribute("loopNo"))
                phase = int(he.getAttribute("phase"))
                holderEnable = int(he.getAttribute("enable"))
                holder = Holder(holderNo, holderEnable, lineNo, phase, loopNo)

                term.addHolder(holder)

        logging.info("load lamp data successful")
    except Exception as e:
        print e
        logging.error("parse %s error" % setting.LAMPS_FILE_PATH)
        logging.info("load lamp data fail")
        _terms = []


def saveAutoTasks():
    impl = minidom.getDOMImplementation()
    dom = impl.createDocument(None, 'tasks', None)
    root = dom.documentElement

    termTaskEle = dom.createElement("termAutoTasks")
    root.appendChild(termTaskEle)
    for holder in getAllHolder():
        if holder.autoTasksSize() == 0:
            continue

        controller = dom.createElement('term')
        controller.setAttribute("lampNo", "%d" % holder.holderNo)

        for autoCtrlTask in holder.autoTasks:
            if autoCtrlTask:
                ele = dom.createElement("task")
                ele.setAttribute("no", "%d" % autoCtrlTask.no)
                ele.setAttribute("timeType", "%d" % autoCtrlTask.timeType)
                ele.setAttribute("ctrlType", "%d" % autoCtrlTask.ctrlType)
                ele.setAttribute("level", "%d" % autoCtrlTask.level)
                ele.setAttribute("relativeTime", "%d" % autoCtrlTask.relativeTime)
                ele.setAttribute("absoluteTime", "%s" % autoCtrlTask.absoluteTime.
                                 strftime("%Y-%m-%d %H:%M:%S"))

                controller.appendChild(ele)

        termTaskEle.appendChild(controller)

    groupTaskEle = dom.createElement("groupAutoTasks")
    root.appendChild(groupTaskEle)
    for group in _groups:
        controller = dom.createElement('group')
        controller.setAttribute("groupNo", "%d" % group.groupNo)

        for autoCtrlTask in group.autoTasks:
            if autoCtrlTask:
                ele = dom.createElement("task")
                ele.setAttribute("no", "%d" % autoCtrlTask.no)
                ele.setAttribute("timeType", "%d" % autoCtrlTask.timeType)
                ele.setAttribute("ctrlType", "%d" % autoCtrlTask.ctrlType)
                ele.setAttribute("level", "%d" % autoCtrlTask.level)
                ele.setAttribute("relativeTime", "%d" % autoCtrlTask.relativeTime)
                ele.setAttribute("absoluteTime", "%s" % autoCtrlTask.absoluteTime.
                                 strftime("%Y-%m-%d %H:%M:%S"))

                controller.appendChild(ele)

        groupTaskEle.appendChild(controller)

    f = open(setting.LAMPS_AUTO_TASK_PATH, 'w')
    dom.writexml(f, addindent='  ', newl='\n', encoding='utf-8')
    f.close()
    os.system("sync")

def loadAutoTasks():
    if not os.path.exists(setting.LAMPS_AUTO_TASK_PATH):
        logging.warn("%s not exist" % setting.LAMPS_AUTO_TASK_PATH)
        return

    try:
        doc = minidom.parse(setting.LAMPS_AUTO_TASK_PATH)
        root = doc.documentElement

        termTaskEle = root.getElementsByTagName("termAutoTasks")[0]
        termElements = termTaskEle.getElementsByTagName("term")
        for termEle in termElements:
            lampNo = int(termEle.getAttribute("lampNo"))

            holder = findHolder(lampNo)
            if not holder:
                continue

            taskEles = termEle.getElementsByTagName("task")
            for taskEle in taskEles:
                task = AutoCtrlTask()
                task.no = int(taskEle.getAttribute("no"))
                task.timeType = int(taskEle.getAttribute("timeType"))
                task.ctrlType = int(taskEle.getAttribute("ctrlType"))
                task.level = int(taskEle.getAttribute("level"))
                task.relativeTime = int(taskEle.getAttribute("relativeTime"))
                absoluteTime = taskEle.getAttribute("absoluteTime")
                task.absoluteTime = datetime.datetime.strptime(absoluteTime, "%Y-%m-%d %H:%M:%S")

                holder.addAutoTasks(task)

        groupTaskEle = root.getElementsByTagName("groupAutoTasks")[0]
        groupElements = groupTaskEle.getElementsByTagName("group")
        for groupEle in groupElements:
            groupNo = int(groupEle.getAttribute("groupNo"))

            group = getGroup(groupNo)

            taskEles = groupEle.getElementsByTagName("task")
            for taskEle in taskEles:
                task = AutoCtrlTask()
                task.no = int(taskEle.getAttribute("no"))
                task.timeType = int(taskEle.getAttribute("timeType"))
                task.ctrlType = int(taskEle.getAttribute("ctrlType"))
                task.level = int(taskEle.getAttribute("level"))
                task.relativeTime = int(taskEle.getAttribute("relativeTime"))
                absoluteTime = taskEle.getAttribute("absoluteTime")
                task.absoluteTime = datetime.datetime.strptime(absoluteTime, "%Y-%m-%d %H:%M:%S")

                group.addAutoTasks(task)

        logging.info("load auto task successful")
    except Exception as e:
        logging.error("parse %s error" % setting.LAMPS_AUTO_TASK_PATH)
        logging.info("load auto task fail")


def addPlanLampTasks(task):
    exist = None
    for t in _planLampTasks:
        if task.No == t.No:
            exist = t
            break
    if not exist:
        _planLampTasks.append(task)
    else:
        _planLampTasks.remove(exist)
        _planLampTasks.append(task)


def addPlanGroupTask(task):
    exist = None
    for t in _planGroupTasks:
        if task.No == t.No:
            exist = t
            break
    if not exist:
        _planGroupTasks.append(task)
    else:
        _planGroupTasks.remove(exist)
        _planGroupTasks.append(task)


def addPlanTermTask(task):
    exist = None
    for t in _planTermTasks:
        if task.No == t.No:
            exist = t
            break
    if not exist:
        _planTermTasks.append(task)
    else:
        _planTermTasks.remove(exist)
        _planTermTasks.append(task)


def deletePlanLampTask(lampNo, No):
    remove = []
    if No == 0xff:
        for planTask in _planLampTasks:
            if planTask.holderNo == lampNo:
                remove.append(planTask)
    else:
        for planTask in _planLampTasks:
            if planTask.No == No:
                remove.append(planTask)
                break

    for planTask in remove:
        _planLampTasks.remove(planTask)


def clearPlanLampTask():
    global _planLampTasks
    _planLampTasks = []


def deletePlanGroupTask(groupNo, No):
    remove = []
    if No == 0xff:
        for planTask in _planGroupTasks:
            if planTask.groupNo == groupNo:
                remove.append(planTask)
    else:
        for planTask in _planGroupTasks:
            if planTask.groupNo == No:
                remove.append(planTask)
                break

    for planTask in remove:
        _planGroupTasks.remove(planTask)


def clearPlanGroupTask():
    global _planGroupTasks
    _planGroupTasks = []


def deleteTermPlanTask(deviceId, No):
    remove = []
    if No == 0xff:
        for planTask in _planTermTasks:
            if planTask.deviceId == deviceId:
                remove.append(planTask)
    else:
        for planTask in _planTermTasks:
            if planTask.No == No:
                remove.append(planTask)
                break

    for planTask in remove:
        _planTermTasks.remove(planTask)


def clearTermPlanTask():
    global _planTermTasks
    _planTermTasks = []


def savePlanTask():
    impl = minidom.getDOMImplementation()
    dom = impl.createDocument(None, 'plan', None)
    root = dom.documentElement

    lampEle = dom.createElement("lampPlan")
    root.appendChild(lampEle)

    for task in _planLampTasks:
        ele = dom.createElement("task")
        ele.setAttribute("No", "%d" % task.No)
        ele.setAttribute("planTime", "%s" % task.planTime.strftime("%Y-%m-%d %H:%M:%S"))
        ele.setAttribute("optType", "%d" % task.optType)
        ele.setAttribute("level", "%d" % task.level)
        ele.setAttribute("holderNo", "%d" % task.holderNo)

        ele.setAttribute("finished", "%d" % int(task.finished))

        lampEle.appendChild(ele)

    groupPlan = dom.createElement("groupPlan")
    root.appendChild(groupPlan)

    for task in _planGroupTasks:
        ele = dom.createElement("task")
        ele.setAttribute("No", "%d" % task.No)
        ele.setAttribute("planTime", "%s" % task.planTime.strftime("%Y-%m-%d %H:%M:%S"))
        ele.setAttribute("optType", "%d" % task.optType)
        ele.setAttribute("level", "%d" % task.level)
        ele.setAttribute("groupNo", "%d" % task.groupNo)

        ele.setAttribute("finished", "%d" % int(task.finished))

        groupPlan.appendChild(ele)

    termPlan = dom.createElement("termPlan")
    root.appendChild(termPlan)

    for task in _planTermTasks:
        ele = dom.createElement("task")
        ele.setAttribute("No", "%d" % task.No)
        ele.setAttribute("planTime", "%s" % task.planTime.strftime("%Y-%m-%d %H:%M:%S"))
        ele.setAttribute("optType", "%d" % task.optType)
        ele.setAttribute("level", "%d" % task.level)
        # ele.setAttribute("groupNo", "%d" % task.groupNo)

        ele.setAttribute("finished", "%d" % int(task.finished))

        termPlan.appendChild(ele)

    f = open(setting.PLAN_TASK_PATH, 'w')
    dom.writexml(f, addindent='  ', newl='\n', encoding='utf-8')

    os.system("sync")


def loadPlanTask():
    global _planGroupTasks, _planLampTasks
    if not os.path.exists(setting.PLAN_TASK_PATH):
        logging.warn("%s not exist" % setting.PLAN_TASK_PATH)
        return

    try:
        doc = minidom.parse(setting.PLAN_TASK_PATH)
        root = doc.documentElement

        lampPlanEle = root.getElementsByTagName("lampPlan")[0]
        taskEles = lampPlanEle.getElementsByTagName("task")
        for ele in taskEles:
            planTask = PlanTask(PlanTask.HOLDER_TASK)
            planTask.No = int(ele.getAttribute("No"))
            planTask.level = int(ele.getAttribute("level"))
            planTask.optType = int(ele.getAttribute("optType"))
            planTask.finished = bool(int(ele.getAttribute("finished")))

            planTask.holderNo = int(ele.getAttribute("holderNo"))

            planTime = ele.getAttribute("planTime")
            planTask.planTime = datetime.datetime.strptime(planTime, "%Y-%m-%d %H:%M:%S")

            _planLampTasks.append(planTask)

        groupPlanEle = root.getElementsByTagName("groupPlan")[0]
        taskEles = groupPlanEle.getElementsByTagName("task")
        for ele in taskEles:
            planTask = PlanTask(PlanTask.GROUP_TASK)
            planTask.No = int(ele.getAttribute("No"))
            planTask.level = int(ele.getAttribute("level"))
            planTask.optType = int(ele.getAttribute("optType"))
            planTask.finished = bool(int(ele.getAttribute("finished")))

            planTask.groupNo = int(ele.getAttribute("groupNo"))

            planTime = ele.getAttribute("planTime")
            planTask.planTime = datetime.datetime.strptime(planTime, "%Y-%m-%d %H:%M:%S")

            _planGroupTasks.append(planTask)

        termPlanEle=root.getElementsByTagName("termPlan")[0]
        taskEles=termPlanEle.getElementsByTagName("task")
        for ele in taskEles:
            planTask = PlanTask(PlanTask.TERM_TASK)
            planTask.No = int(ele.getAttribute("No"))
            planTask.level = int(ele.getAttribute("level"))
            planTask.optType = int(ele.getAttribute("optType"))
            planTask.finished = bool(int(ele.getAttribute("finished")))

            # planTask.groupNo = int(ele.getAttribute("groupNo"))

            planTime = ele.getAttribute("planTime")
            planTask.planTime = datetime.datetime.strptime(planTime, "%Y-%m-%d %H:%M:%S")

            _planTermTasks.append(planTask)

        logging.info("load plan task successful")
    except Exception as e:
        logging.error("parse %s error. %r" % (setting.PLAN_TASK_PATH, e.message))
        logging.info("load plan task fail")
        _planGroupTasks = []
        _planLampTasks = []


def _findPlanTask(year, month, day, planTaskList):
    tasks = []
    t = datetime.datetime(year, month, day)

    for planTask in planTaskList:
        if planTask.planTime.year == t.year \
                and planTask.planTime.month == t.month \
                and planTask.planTime.day == t.day:
            tasks.append(planTask)

    return tasks


def findLampPlanTask(year, month, day):
    return _findPlanTask(year, month, day, _planLampTasks)


def findGroupPlanTask(year, month, day):
    return _findPlanTask(year, month, day, _planGroupTasks)

def findRtuPlanTask(year, month, day):
    return _findPlanTask(year, month, day, _planTermTasks)

def getGroup(groupNo):
    for group in _groups:
        if group.groupNo == groupNo:
            return group

    group = Group(groupNo)
    _groups.append(group)
    return group


def allGroup():
    return _groups


def saveGroup():
    pass